﻿
// TODO : Redo this crap class so that the method param's arent a mile long

namespace SwtorCalculator {
    using System;

    /// <summary>
    /// Abilities Parent Class
    /// General formula method calls
    /// </summary>
    internal class Abilities {
        /// <summary>
        /// Initializes a New Instance of the Abilities Class
        /// </summary>
        protected Abilities() { }

        /// <summary>
        /// Returns Mobs Current Mitigation
        /// </summary>
        /// <param name="armor">Mobs Current Armor</param>
        /// <param name="level">Mobs Level</param>
        /// <returns>The Mobs Current Mitigation</returns>
        private double MobMitigation( double armor, int level ) {
            return armor / ( armor + ( 200 * level ) + 800 );
        }

        /// <summary>
        /// Adjusted Hit/Crit
        /// </summary>
        /// <param name="totalHitChance">Characters Total Hit Chance</param>
        /// <param name="totalCritChance">Characters Total Crit Chance</param>
        /// <param name="totalCritDamage">Characters Total Crit Damage</param>
        /// <returns>The Adjusted Hit/Crit</returns>
        private double MeleeCritHitAdjustment( double totalHitChance, double totalCritChance, double totalCritDamage ) {
            return ( ( 1 + totalCritChance ) * totalCritDamage ) * totalHitChance; /*Need to add to base miss*/
        }

        /// <summary>
        /// Base Average Melee Damage
        /// </summary>
        /// <param name="spd">Characters Weapon Speed</param>
        /// <param name="dps">Characters Weapon DPS</param>
        /// <param name="bonusDmg">Characters Total Bonus Damage</param>
        /// <returns>The Average Melee Damage</returns>
        private double MeleeAveBaseDmg( double spd, double dps, double bonusDmg ) {
            return ( spd * dps ) + bonusDmg;
        }

        /// <summary>
        /// Adjusted Melee Base Damage
        /// For fast DPS Calculations
        /// </summary>
        /// <param name="spd">Characters Weapon Speed</param>
        /// <param name="dps">Characters Weapon DPS</param>
        /// <param name="bonusDmg">Characters Total Bonus Damage</param>
        /// <param name="totalHitChance">Characters Total Hit Chance</param>
        /// <param name="totalCritChance">Characters Total Crit Chance</param>
        /// <param name="totalCritDamage">Characters Total Crit Damage</param>
        /// <returns>The Adjusted Melee Base Damage</returns>
        private double MeleeModifiedBase( double spd, double dps, double bonusDmg, double totalHitChance, double totalCritChance, double totalCritDamage ) {
            return MeleeAveBaseDmg( spd, dps, bonusDmg ) * MeleeCritHitAdjustment( totalHitChance, totalCritChance, totalCritDamage ); // * TalentDmgMods * BuffDmgMods)
        }

        /// <summary>
        /// Quick Average Melee Damage
        /// </summary>
        /// <param name="spd">Characters Weapon Speed</param>
        /// <param name="dps">Characters Weapon DPS</param>
        /// <param name="bonusDmg">Characters Total Bonus Damage</param>
        /// <param name="totalHitChance">Characters Total Hit Chance</param>
        /// <param name="totalCritChance">Characters Total Crit Chance</param>
        /// <param name="totalCritDamage">Characters Total Crit Damage</param>
        /// <param name="totalArPen">Characters Total Armor Penetration</param>
        /// <param name="mobArmor">The Mobs Current Armor</param>
        /// <returns>The Quick Average Melee Damage</returns>
        protected double QuickAveDamage( double spd, double dps, double bonusDmg, double totalHitChance, double totalCritChance, double totalCritDamage, double totalArPen, double mobArmor ) {
            return MeleeModifiedBase( spd, dps, bonusDmg, totalHitChance, totalCritChance, totalCritDamage ) * ( 1 - MobMitigation( mobArmor * ( 1 - totalArPen ), 53 ) ); // * GlanceMod
            // Should probably pass it boss armor and have a calculation in here so I can use ArPen here
        }

        /// <summary>
        /// Quick Melee DPS
        /// </summary>
        /// <param name="spd">Characters Weapon Speed</param>
        /// <param name="dps">Characters Weapon DPS</param>
        /// <param name="bonusDmg">Characters Total Bonus Damage</param>
        /// <param name="totalHitChance">Characters Total Hit Chance</param>
        /// <param name="totalCritChance">Characters Total Crit Chance</param>
        /// <param name="totalCritDamage">Characters Total Crit Damage</param>
        /// <param name="totalArPen">Characters Total Armor Penetration</param>
        /// <param name="mobArmor">The Mobs Current Armor</param>
        /// <returns>The Quick Melee DPS</returns>
        internal double QuickDPSFigure( double spd, double dps, double bonusDmg, double totalHitChance, double totalCritChance, double totalCritDamage, double totalArPen, double mobArmor ) {
            return QuickAveDamage( spd, dps, bonusDmg, totalHitChance, totalCritChance, totalCritDamage, totalArPen, mobArmor ) / spd;
        }

        /// <summary>
        /// Average Gain from 'On Click' Trinkets
        /// </summary>
        /// <param name="buffAmount">The Amount of the 'On Click' Buff</param>
        /// <param name="duration">Duration of the Buff</param>
        /// <param name="cooldown">The Cooldown of the 'On Click' Item</param>
        /// <returns>The Average Buff Gain</returns>
        protected double OnClickAverage( double buffAmount, int duration, int cooldown ) {
            return buffAmount * ( double )duration / ( double )cooldown;
        }

        /// <summary>
        /// Determines the Chance to Proc an Effect That Is PPM Based
        /// </summary>
        /// <param name="weapSpeed">Players Current Swing Speed</param>
        /// <param name="ppm">Items PPM Rate</param>
        /// <returns>The PPM Proc Chance</returns>
        protected double ProcPerMinuteChance( double weapSpeed, double ppm ) {
            return weapSpeed * ppm / 60;
        }

        /// <summary>
        /// Average Uptime of a Proc That Doesn't Have an Internal Cooldown
        /// </summary>
        /// <param name="procChance">Chance to Proc</param>
        /// <param name="duration">Duration of the Buff</param>
        /// <param name="attacksPerSec">Players Current Average Attacks Per Second</param>
        /// <returns>Average Proc Uptime</returns>
        protected double ProcUptimeNoCd( double procChance, int duration, double attacksPerSec ) {
            return 1 - Math.Pow( ( 1 - procChance ), ( duration * attacksPerSec ) );
        }

        /// <summary>
        /// Average Uptime of a Proc That Has an Internal Cooldown
        /// </summary>
        /// <param name="procChance">Chance to Proc</param>
        /// <param name="duration">Duration of the Buff</param>
        /// <param name="internCd">Proc Internal Cooldown</param>
        /// <param name="attacksPerSec">Players Current Average Attacks Per Second</param>
        /// <returns>Average Proc Uptime</returns>
        protected double ProcUptimeWithCd( double procChance, int duration, int internCd, double attacksPerSec ) {
            return ( duration / internCd ) + ( 1 / ( attacksPerSec * procChance ) );
        }
    }
}
